#include <iostream>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>

typedef websocketpp::server<websocketpp::config::asio> websocketsvr;
typedef websocketsvr::message_ptr message_ptr;
void print(const std::string& str)
{
    std::cout<<str<<std::endl;
}
// 客户端发起了http请求，会调用这个函数
void http_callback(websocketsvr *server, websocketpp::connection_hdl hdl)
{
    // 给客户端返回一个hello world的页面
    // 声明一个名为con的变量，它是一个智能指针，指向由hdl句柄标识的WebSocket连接对象。
    websocketsvr::connection_ptr conn = server->get_con_from_hdl(hdl);
    std::cout << "body: " << conn->get_request_body() << std::endl;
    // 获取连接请求信息
    websocketpp::http::parser::request req = conn->get_request();
    std::cout << "method: " << req.get_method() << std::endl;
    std::cout << "uri: " << req.get_uri() << std::endl;
    std::string body = "<html><body><h1>Hello World</h1></body></html>";
    // conn->set_body(body);
    // conn->append_header("Content-Type", "text/html");
    conn->set_body(conn->get_request_body());
    conn->set_status(websocketpp::http::status_code::ok);
    websocketsvr::timer_ptr tp = server->set_timer(5000,std::bind(print,"hello world!"));
    tp->cancel();
}
void wbopen_callback(websocketsvr *server, websocketpp::connection_hdl hdl)
{
    std::cout << "websocket握手成功！！\n";
}
void wbclose_callback(websocketsvr *server, websocketpp::connection_hdl hdl)
{
    std::cout << "websocket连接断开！！\n";
}
//message_ptr msg: 一个智能指针，指向接收到的WebSocket消息对象。
void wbmessage_callback(websocketsvr *server, websocketpp::connection_hdl hdl, message_ptr msg)
{
    websocketsvr::connection_ptr conn = server->get_con_from_hdl(hdl);
    //msg->get_payload()是websocketpp库中message类的一个方法，它返回消息的有效载荷，即实际发送的数据。
    std::cout << "wsmsg: " << msg->get_payload() << std::endl;
    std::string rsp = "client say: " + msg->get_payload();
    //发送构造好的响应应答，send方法是websocketpp库中连接类的一个方法，它用于发送数据。第二个参数指定了帧类型，text：发送的是文本数据
    conn->send(rsp, websocketpp::frame::opcode::text);
}
int main()
{
    // 使用websocketpp库创建服务器
    websocketsvr server;
    // 设置websocketpp库的日志级别
    // none表示什么日志都不打印
    server.set_access_channels(websocketpp::log::alevel::none);
    /*初始化asio*/
    server.init_asio();
    // 注册http请求的处理函数
    server.set_http_handler(bind(http_callback, &server, std::placeholders::_1));
    // 注册websocket请求的处理函数
    server.set_open_handler(bind(wbopen_callback, &server, std::placeholders::_1));
    server.set_close_handler(bind(wbclose_callback, &server, std::placeholders::_1));
    server.set_message_handler(bind(wbmessage_callback, &server, std::placeholders::_1, std::placeholders::_2));
    // 监听8888端口
    server.listen(8888);
    // 开始接收tcp连接
    server.start_accept();
    // 开始运行服务器
    server.run();
    return 0;
}